/*
 * This software code is (c) 2010 T-Mobile USA, Inc. All Rights Reserved.
 *
 * Unauthorized redistribution or further use of this material is
 * prohibited without the express permission of T-Mobile USA, Inc. and
 * will be prosecuted to the fullest extent of the law.
 *
 * Removal or modification of these Terms and Conditions from the source
 * or binary code of this software is prohibited.  In the event that
 * redistribution of the source or binary code for this software is
 * approved by T-Mobile USA, Inc., these Terms and Conditions and the
 * above copyright notice must be reproduced in their entirety and in all
 * circumstances.
 *
 * No name or trademarks of T-Mobile USA, Inc., or of its parent company,
 * Deutsche Telekom AG or any Deutsche Telekom or T-Mobile entity, may be
 * used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" AND "WITH ALL FAULTS" BASIS
 * AND WITHOUT WARRANTIES OF ANY KIND.  ALL EXPRESS OR IMPLIED
 * CONDITIONS, REPRESENTATIONS OR WARRANTIES, INCLUDING ANY IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT CONCERNING THIS SOFTWARE, ITS SOURCE OR BINARY CODE
 * OR ANY DERIVATIVES THEREOF ARE HEREBY EXCLUDED.  T-MOBILE USA, INC.
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
 * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE
 * OR ITS DERIVATIVES.  IN NO EVENT WILL T-MOBILE USA, INC. OR ITS
 * LICENSORS BE LIABLE FOR LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
 * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES,
 * HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT
 * OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF T-MOBILE USA,
 * INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * THESE TERMS AND CONDITIONS APPLY SOLELY AND EXCLUSIVELY TO THE USE,
 * MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE, ITS SOURCE OR BINARY
 * CODE OR ANY DERIVATIVES THEREOF, AND ARE SEPARATE FROM ANY WRITTEN
 * WARRANTY THAT MAY BE PROVIDED WITH A DEVICE YOU PURCHASE FROM T-MOBILE
 * USA, INC., AND TO THE EXTENT PERMITTED BY LAW.
 */

package javax.microedition.ims.core.dispatcher;

import javax.microedition.ims.common.Consumer;
import javax.microedition.ims.common.IMSMessage;
import javax.microedition.ims.common.ProducerListener;
import javax.microedition.ims.core.ConsumerRegistryIMS;
import javax.microedition.ims.core.StackContext;
import javax.microedition.ims.core.transaction.TransactionRunnable;
import javax.microedition.ims.core.transaction.TransactionUtils;
import javax.microedition.ims.core.xdm.XDMMessage;
import java.util.List;

/**
 * @author ext-plabada
 */
public class MessageDispatcherXDM extends MessageDispatcherBase<XDMMessage> {

    //private final StackContext context;

    public MessageDispatcherXDM(
            final StackContext context,
            final ProducerListener<IMSMessage> outMsgProducerListener) {
        super(new ConsumerRegistryIMS<XDMMessage>(), outMsgProducerListener);

        //this.context = context;
    }

    
    protected Consumer<XDMMessage> createOuterConsumer() {

        return new Consumer<XDMMessage>() {
            
            public void push(final XDMMessage msg) {
                doPush(msg);
            }

            private void doPush(final XDMMessage msg) {

                TransactionUtils.invokeLater(
                        new TransactionRunnable("MessageDispatcher.outerConsumer :" + msg.shortDescription()) {
                            
                            public void run() {
                                onOuterMessageIncome(msg);
                            }
                        }
                );
            }
        };
    }

    private void onOuterMessageIncome(final XDMMessage msg) {
        if (!done.get()) {

            List<Consumer<XDMMessage>> filteredConsumers = getFilteredConsumers(msg);

            assert filteredConsumers.size() <= 1 : filteredConsumers.size() +
                    " consumers for incoming message " + msg.shortDescription();

            if (messageCanBeAddressed(filteredConsumers)) {

                feedConsumers(filteredConsumers, msg);
            }
            else {
                /*try {
                    unknownMessageResolver.resolveMessage(msg);
                } catch (DialogStateException e) {
                    handleDialogStateException(e);
                }*/
            }
        }
    }


    
    protected Consumer<XDMMessage> createInnerConsumer() {
        return new Consumer<XDMMessage>() {
            
            public void push(final XDMMessage msg) {
                onInnerMessageIncome(msg);
            }
        };
    }

    private void onInnerMessageIncome(final XDMMessage msg) {
        if (!done.get()) {
            sendMessageOutside(msg);
        }
    }


    private boolean messageCanBeAddressed(final List<?> filteredConsumers) {
        return filteredConsumers != null && filteredConsumers.size() != 0;
    }

    protected void feedConsumers(final List<Consumer<XDMMessage>> consumers, final XDMMessage msg) {
        super.feedConsumers(consumers, msg);
    }


    public void shutdown() {
        if (done.compareAndSet(false, true)) {
            super.shutdown();
        }
    }
}
